package com.wkbb.basic.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wkbb.basic.feign.WxFeignService;
import com.wkbb.basic.mapper.DeviceBoxMapper;
import com.wkbb.basic.mapper.YoutuPersonMapper;
import com.wkbb.basic.model.DeviceBox;
import com.wkbb.basic.model.YoutuPerson;
import com.wkbb.basic.service.DeviceBoxService;
import com.wkbb.basic.service.JvtBoxService;
import com.wkbb.basic.service.UserFaceService;
import com.wkbb.basic.utils.jvt.JvtBoxBean;
import com.wkbb.basic.utils.jvt.JvtBoxUtil;
import com.wkbb.common.base.BaseServiceImpl;
import com.wkbb.common.business.BasicBusiness;
import com.wkbb.common.dto.basic.DeviceBoxDto;
import com.wkbb.common.dto.basic.UserFaceDto;
import com.wkbb.common.redis.RedisTemplateUtil;
import com.wkbb.common.utils.StringUtil;
import com.wkbb.common.utils.ThreadPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Lilin
 */
@Service
@Slf4j
public class DeviceBoxServiceImpl extends BaseServiceImpl<DeviceBox> implements DeviceBoxService {

    @Autowired
    private DeviceBoxMapper deviceBoxMapper;

    @Autowired
    private UserFaceService userFaceService;

    @Autowired
    private YoutuPersonMapper youtuPersonMapper;

    @Autowired
    private JvtBoxService jvtBoxService;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Autowired
    public void setMapper(DeviceBoxMapper mapper) {
        super.setMapper(mapper);
    }

    @Override
    public void insert(DeviceBox entity) throws Exception {

        //覆盖IPC配置
        if (entity.getDeviceCameras() != null) {
            unbindBoxByCamera(entity.getId(), entity.getDeviceCameras());
        }

        super.insert(entity);
        DeviceBoxDto deviceBoxDto = new DeviceBoxDto();
        BeanUtils.copyProperties(entity, deviceBoxDto);
        redisTemplateUtil.set(BasicBusiness.getBoxRedisKey(entity.getDeviceCode(), entity.getId().toString()), deviceBoxDto);
    }

    @Override
    public void update(DeviceBox entity) throws Exception {

        //覆盖IPC配置
        if (entity.getDeviceCameras() != null) {
            unbindBoxByCamera(entity.getId(), entity.getDeviceCameras());
        }

        super.update(entity);
//        DeviceBoxDto deviceBoxDto = new DeviceBoxDto();
//        BeanUtils.copyProperties(entity, deviceBoxDto);
//        redisTemplateUtil.set(BasicBusiness.getBoxRedisKey(entity.getDeviceCode(), entity.getId().toString()), deviceBoxDto);
        //清除redis缓存
        redisTemplateUtil.delKeysLike(BasicBusiness.getBoxRedisKey("*", entity.getId().toString()));
    }

    @Override
    public void deleteBoxBatchByIds(List<Long> ids) throws Exception {
        for (Long id : ids) {
            DeviceBox box = super.getByPrimaryKey(id);
            //清空盒子人脸
            if (box == null) {
                continue;
            }
            jvtBoxService.pushDeleteJvtPersonListTask(box.getDeviceCode(), JvtBoxUtil.TYPE_WHITE_LIST);
            redisTemplateUtil.delKeysLike(BasicBusiness.getBoxRedisKey("*", id.toString()));
        }
        deviceBoxMapper.deleteBoxBatchByIds(ids);
    }

    @Override
    public List<DeviceBoxDto> getDeviceBoxList(Long orgId, String orgName, String name, String deviceCode, String deviceSerial, String deviceMac, Short scene, Boolean active) {
        Map<String, Object> params = new HashMap<>(3);
        if (orgId != null && orgId != 0) {
            params.put("orgId", orgId);
        }
        if (!StringUtil.isNullOrBlank(orgName)) {
            params.put("orgName", orgName);
        }
        if (!StringUtil.isNullOrBlank(name)) {
            params.put("name", name);
        }
        if (!StringUtil.isNullOrBlank(deviceCode)) {
            params.put("deviceCode", deviceSerial);
        }
        if (!StringUtil.isNullOrBlank(deviceSerial)) {
            params.put("deviceSerial", deviceSerial);
        }
        if (!StringUtil.isNullOrBlank(deviceMac)) {
            params.put("deviceMac", deviceMac);
        }
        if (scene != null && scene != 0) {
            params.put("scene", scene);
        }
        if (active != null) {
            params.put("active", active ? 1 : 0);
        }

        return deviceBoxMapper.getDeviceBoxList(params);
    }

    @Override
    public PageInfo<DeviceBoxDto> getDeviceBoxPageList(Long orgId, String orgName, String name, String deviceCode, String deviceSerial, String deviceMac, Short scene, Boolean active, Integer pageNo, Integer pageSize) {
        if (pageNo == null || pageSize == null) {
            return null;
        }

        Page<DeviceBoxDto> page = PageHelper.startPage(pageNo, pageSize, true);
        PageInfo<DeviceBoxDto> pageInfo = new PageInfo<>(getDeviceBoxList(orgId, orgName, name, deviceCode, deviceSerial, deviceMac, scene, active));
        pageInfo.setTotal(page.getTotal());
        return pageInfo;
    }

    @Override
    public DeviceBoxDto getDeviceBoxInfo(Long id) {
        Map<String, Object> params = new HashMap<>(1);
        params.put("id", id);
        DeviceBoxDto entity = deviceBoxMapper.getDeviceBoxInfo(params);
        if (entity == null) {
            return null;
        }
        //更新redis
        redisTemplateUtil.set(BasicBusiness.getBoxRedisKey(entity.getDeviceCode(), entity.getId().toString()), entity);
        return entity;
    }

    @Override
    public DeviceBoxDto getDeviceBoxInfo(String deviceCode) {
        Map<String, Object> params = new HashMap<>(1);
        params.put("deviceCode", deviceCode);
        DeviceBoxDto entity = deviceBoxMapper.getDeviceBoxInfo(params);
        if (entity == null) {
            return null;
        }
        entity.setDeviceCameraList(null);
        //更新redis
        redisTemplateUtil.set(BasicBusiness.getBoxRedisKey(entity.getDeviceCode(), entity.getId().toString()), entity);
        return entity;
    }

    private List<DeviceBox> getDeviceBoxListByOrgId(Long orgId) {
        Map<String, Object> params = new HashMap<>(1);
        params.put("orgId", orgId);

        //2.找到组织所有已激活的盒子
        List<DeviceBox> deviceBoxList = deviceBoxMapper.getDeviceBoxListByOrgs(params);
        if (deviceBoxList == null || deviceBoxList.isEmpty()) {
            log.warn("【巨龙】组织{},无激活盒子", orgId);
            return null;
        }
        log.info("【巨龙】组织{},已激活盒子:{}", orgId, Arrays.toString(deviceBoxList.toArray()));
        return deviceBoxList;
    }

    @Override
    public void addBoxPerson(String personId, String picUrl) {
        log.info("【巨龙】向巨龙盒子添加人员 personId:{}，picUrl:{}", personId, picUrl);
        YoutuPerson youtuPerson = youtuPersonMapper.getPersonByPersonId(personId);
        if (youtuPerson == null) {
            log.warn("【巨龙】查无此人 personId:{}", personId);
            return;
        }

        if (youtuPerson.getOrgId() == null || youtuPerson.getOrgId() == 0) {
            log.warn("【巨龙】此人无对应组织ID personId:{}", personId);
            return;
        }
        List<DeviceBox> deviceBoxList = getDeviceBoxListByOrgId(youtuPerson.getOrgId());
        if (deviceBoxList == null || deviceBoxList.isEmpty()) {
            log.info("【巨龙】该组织无激活盒子 orgId:{}", youtuPerson.getOrgId());
            return;
        }

        //3.向盒子添加人员
        for (DeviceBox deviceBox : deviceBoxList) {
            try {
                jvtBoxService.pushAddJvtPersonTask(deviceBox.getDeviceCode(), JvtBoxUtil.TYPE_WHITE_LIST, personId, picUrl);
            } catch (Exception e) {
                log.error("【巨龙】添加人员（加入队列）失败 orgId:{},UUID:{},e:{}", deviceBox.getOrgId(), deviceBox.getDeviceCode(), e);
            }
        }

    }

    @Override
    public void deleteBoxPerson(String personId,Long orgId) {
        log.info("【巨龙】向巨龙盒子删除人员 personId:{}，picUrl:{}", personId);


        List<DeviceBox> deviceBoxList = getDeviceBoxListByOrgId(orgId);
        if (deviceBoxList == null || deviceBoxList.isEmpty()) {
            log.info("【巨龙】该组织无激活盒子 orgId:{}", orgId);
            return;
        }

        //3.向盒子添加人员
        for (DeviceBox deviceBox : deviceBoxList) {
            try {
                jvtBoxService.pushDeleteJvtPersonTask(deviceBox.getDeviceCode(), JvtBoxUtil.TYPE_WHITE_LIST, personId);
            } catch (Exception e) {
                log.error("【巨龙】删除人员（加入队列）失败 orgId:{},UUID:{},e:{}", deviceBox.getOrgId(), deviceBox.getDeviceCode(), e);
            }
        }

    }

    @Override
    public boolean updateBoxActive(String name, DeviceBox deviceBox, Boolean active) throws Exception {
        log.info("【巨龙】激活巨龙盒子 UUID:{}", deviceBox.getDeviceCode());
        DeviceBox updateDeviceBox = new DeviceBox();
        updateDeviceBox.setId(deviceBox.getId());
        updateDeviceBox.setUpdateBy(name);
        updateDeviceBox.setActive(active);
        deviceBoxMapper.updateBoxActive(updateDeviceBox);

        if (active) {
            //激活前将盒子推送地址设置好
            JvtBoxBean result = null;
            try {
                result = jvtBoxService.setJvtParams(deviceBox.getDeviceCode());
            } catch (Exception ignored) {
            }
            if (result == null || result.getCode() != 1) {
                log.warn("【巨龙】盒子不在线或版本过低，配置盒子推送地址失败");
                return false;
            } else {
                log.warn("【巨龙】配置盒子推送地址成功");
            }

            log.info("【巨龙】清空设备任务队列 UUID:{}", deviceBox.getDeviceCode());
            redisTemplateUtil.delKeysLike(jvtBoxService.getTaskKey(deviceBox.getDeviceCode()));

            log.info("【巨龙】清空设备人脸 UUID:{}", deviceBox.getDeviceCode());
            jvtBoxService.pushDeleteJvtPersonListTask(deviceBox.getDeviceCode(), JvtBoxUtil.TYPE_WHITE_LIST);

            log.info("【巨龙】同步人脸数据 UUID:{}", deviceBox.getDeviceCode());
            syncUser(deviceBox);
        }
        return true;
    }

    /**
     * 覆盖绑定IPC
     *
     * @param boxId         盒子ID
     * @param deviceCameras IPC列表
     */
    private void unbindBoxByCamera(Long boxId, Object deviceCameras) throws Exception {
        JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(deviceCameras));
        for (Object o : jsonArray) {
            Map<String, Object> params = new HashMap<>(1);
            params.put("boxId", boxId);
            params.put("deviceCamera", o);
            List<DeviceBox> deviceBoxList = deviceBoxMapper.getDeviceBoxByCamera(params);
            if (deviceBoxList != null && !deviceBoxList.isEmpty()) {
                for (DeviceBox deviceBox : deviceBoxList) {
                    if (deviceBox.getDeviceCameras() == null) {
                        continue;
                    }

                    JSONArray oldArray = JSON.parseArray(JSON.toJSONString(deviceBox.getDeviceCameras()));
                    //从原来的盒子删除IPC
                    oldArray.remove(o);

                    deviceBox.setDeviceCameras(oldArray);
                    super.update(deviceBox);
                    log.info("将{}盒子绑定的{}IPC转移到{}盒子", deviceBox.getId(), o, boxId);
                }
            }
        }
    }

    private void syncUser(DeviceBox deviceBox) {
        List<UserFaceDto> userFaceList = userFaceService.getUserFaceImgByOrg(deviceBox.getOrgId());
        if (userFaceList == null || userFaceList.isEmpty()) {
            log.warn("【巨龙】无人脸数据 UUID:{}", deviceBox.getDeviceCode());
            return;
        }

        ThreadPoolUtil.addTask(() -> {
            int size = userFaceList.size();
            log.info("【巨龙】待同步人脸{}个 ", size);
            for (UserFaceDto userFaceDto : userFaceList) {
                try {
                    jvtBoxService.pushAddJvtPersonTask(deviceBox.getDeviceCode(), JvtBoxUtil.TYPE_WHITE_LIST, userFaceDto.getPersonId(), userFaceDto.getFaceImgUrl());
//                    JvtBoxBean result = JvtBoxUtil.addPerson(deviceBox.getDeviceCode(), JvtBoxUtil.TYPE_WHITE_LIST, userFaceDto.getPersonId(), FileUtil.encodeImageToBase64(new URL(userFaceDto.getFaceImgUrl())));
                } catch (Exception e) {
                    log.error("【巨龙】添加人员(加入队列)失败 orgId:{},UUID:{},e:{}", deviceBox.getOrgId(), deviceBox.getDeviceCode(), e);
                }
            }
        });
    }

}
